﻿using CIS.Common.Grpc.Protos;
using Grpc.Core;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CIS.Common.Grpc
{
    public class GrpcServiceBase:GrpcService.GrpcServiceBase
    {
        private ConcurrentDictionary<string, ClientState> clients = new ConcurrentDictionary<string, ClientState>();
        public Func<GrpcMessage, Task>? OnReceiveAsync { get; set; }
        public Func<GrpcMessage, GrpcMessage>? OnRequestAsync { get; set; }

        /// <summary>
        /// 服务端向客户端发送消息
        /// </summary>
        /// <param name="request"></param>
        /// <param name="responseStream"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task Listen(ClientInfoRequest request, IServerStreamWriter<GrpcMessageData> responseStream, ServerCallContext context)
        {
            ClientState? client;
            clients.TryGetValue(request.ClientName, out client);
            await Task.Run(async () =>
            {
                while (true)
                {
                    if (client != null && client.SendQueue != null)
                    {
                        if (!client.SendQueue.IsEmpty)
                        {
                            GrpcMessageData msg;
                            bool result = client.SendQueue.TryDequeue(out msg);
                            if (result && msg != null)
                            {
                                msg.Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff");
                                await responseStream.WriteAsync(msg);
                            }
                        }
                        await Task.Delay(1500);
                    }
                }
            });
        }

        /// <summary>
        /// 客户端 连接注册 处理方法
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task<RegisterRequestReply> Regist(RegisterRequest request, ServerCallContext context)
        {
            RegisterRequestReply reply = new RegisterRequestReply();
            ClientState? client;
            clients.TryGetValue(request.Client.ClientName, out client);
            if(client == null)
            {
                ClientState clientState = new ClientState();
                clientState.ClientInfo.ClientID = request.Client.ClientID;
                clientState.ClientInfo.ClientName = request.Client.ClientName;
                clients.TryAdd(request.Client.ClientName, clientState);
            }
            reply.Topic = request.Topic;
            reply.Result = true;
            return Task.FromResult(reply);
        }

        /// <summary>
        /// 客户端向服务端发送消息
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task<ReplyMessage> Send(GrpcMessageData request, ServerCallContext context)
        {
            ReplyMessage replyMessage=new ReplyMessage();
            replyMessage.Data = "GrpcServer Is Connect";
            GrpcMessage receivedMsg= new GrpcMessage(request);
            var reply = OnReceiveAsync?.Invoke(receivedMsg);
            return Task.FromResult(replyMessage);
        }

        /// <summary>
        /// 客户端回复服务端请求 消息
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task<ReplyMessage> Reply(GrpcMessageData request, ServerCallContext context)
        {
            ClientState? client;
            clients.TryGetValue(request.Sender.ClientName,out client);
            ReplyMessage reply = new ReplyMessage()
            {
                Data = "Server Received Reply"
            };
            if(client != null)
            {
                GrpcMessage replyMsg = new GrpcMessage(request);
                client.ReplyMsg.TryAdd(request.Name, replyMsg);
            }
            return Task.FromResult(reply);
        }
        
        /// <summary>
        /// Server 端向 Client 端发送的消息队列
        /// </summary>
        /// <param name="clientName"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task<GrpcMessage> ServerSendMsg(string clientName,GrpcMessage message)
        {
            ClientState client;
            clients.TryGetValue(clientName, out client);
            if(client != null)
            {
                GrpcMessageData msg = message.GetData();
                client.SendQueue.Enqueue(msg);
                if (message.IsRequest)
                {
                    while (true)
                    {
                        if(client.ReplyMsg != null && client.ReplyMsg.Count > 0)
                        {
                            client.ReplyMsg.TryGetValue(message.Name, out message);
                            break;
                        }
                        await Task.Delay(10);
                    }
                }
            }
            return message;
        }
    }
}
